
#include "ArenaDuplicate.h"
#include "Duplicate/DuplicateMgr.h"
#include "Common/ArenaDefine.h"
#include "Character/PlayerMgr.h"
#include "Character/newAI/behaviac/CreatureCommonAI.h"
#include "Character/HuoYueDuPart.h"

ArenaDuplicate::ArenaDuplicate()
{
	m_byType = (int8_t)EDuplicateType::EDuplicateType_Arena;
	m_bNotifyArena = false;
	//m_historyRankId = MAX_ARENA_NUM+1;
	m_oldPkMode = -1;
	m_oldhp = -1;
	m_oldhp = -1;
	m_bStart = false;
	m_bStartCountDown = false;
}
	
ArenaDuplicate::~ArenaDuplicate()
{

}


//初始化
bool ArenaDuplicate::Init(uint32_t nDuplicateID, uint32_t nSceneID, IBrushMonster *pBrush)
{
	return Duplicate::Init(nDuplicateID, nSceneID, pBrush);
}
//
void ArenaDuplicate::UnInit()
{
	Duplicate::UnInit();
	m_bNotifyArena = false;
	//m_historyRankId = MAX_ARENA_NUM + 1;
	m_oldPkMode = -1;
	m_oldhp = -1;
	m_oldhp = -1;
	m_bStart = false;
	m_bStartCountDown = false;
}



//生物进入场景
void ArenaDuplicate::OnCreatureEnter(Creature *pCreature)
{
	/*if (nullptr == pCreature)
	{
		return;
	}
	if (CREATURE_PLAYER == pCreature->CreatureKind())
	{
		//订阅角色刷怪事件
		if (!g_GetEvent()->Subscribe(this, EVENT_CREATURE_DEAD, pCreature->GetCid(), CREATURE_MONSTER, "TowerDuplicate"))
		{
			LogErrFmtPrint("[logic] TowerDuplicate::EnterDuplicate....Subscribe monster dead event failed....");
		}

		//订阅角色掉线事件
		if (!g_GetEvent()->Subscribe(this, EVENT_DISCONNECT, pCreature->GetCid(), CREATURE_PLAYER, "TowerDuplicate"))
		{
			LogErrFmtPrint("[logic] TowerDuplicate::EnterDuplicate....Subscribe player disconnect event  failed....");
		}

		//订阅角色死亡事件
		if (!g_GetEvent()->Subscribe(this, EVENT_CREATURE_DEAD, pCreature->GetCid(), CREATURE_PLAYER, "TowerDuplicate"))
		{
			LogErrFmtPrint("[logic] TowerDuplicate::EnterDuplicate....Subscribe player dead event  failed....");
		}

		LogDebugFmtPrint("[logic] TowerDuplicate::EnterDuplicate success...cid:%u ,duplicateid:%u, sceneid:%u ", pCreature->GetCid(), m_nDuplicateID, m_nSceneID);
	}*/
	if (nullptr == pCreature)
	{
		return;
	}
	else if (CREATURE_PLAYER == pCreature->CreatureKind())
	{
		Player* pPlayer = dynamic_cast<Player*>(pCreature);
		if (nullptr != pPlayer)
		{
			//m_historyRankId = pPlayer->GetArenaBestRankId();
			//如果进入副本中的角色ID是挑战方ID 那么触发事件
			if (pPlayer->GetCid() == m_paramEx.keyValue)
			{
				//增加挑战次数
				pPlayer->AddArenaChallengeTimes();				//通知前端进入成功				WCArenaChallRsp rsp;				rsp.set_ret(RET_SUCCESS);				pPlayer->SendDataToClient(EMODULE_ID_ARENA, CENTER_TO_CLIENT_ARENA_CHALL, &rsp);				//增加活跃度				HuoYueDuPart* pHuoYueDuPart = dynamic_cast<HuoYueDuPart*>(pPlayer->GetPart(PART_HUOYUEDU));				if (nullptr != pHuoYueDuPart)				{					//增加活跃度					pHuoYueDuPart->AddHuoYueDuRecord(HYDT_ARENA);				}				//参加一次竞技场事件				ArenaJoinEvent arenaJoinEvent;				g_GetEvent()->FireExecute(EVENT_ARENA_JOIN, pPlayer->GetCid(), pPlayer->CreatureKind(), &arenaJoinEvent, sizeof(ArenaJoinEvent));
			}

			//玩家进入竞技场，设置pk 模式
			m_oldPkMode = (int32_t)pPlayer->GetPkMode();
			pPlayer->SetPkMode(PK_MODE_KILLER);
			//设置满血满蓝
			m_oldhp = pPlayer->GetAttr(C_HP);
			m_oldmp = pPlayer->GetAttr(C_MP);
			int64_t maxhp = pPlayer->GetAttr(C_MAX_HP);
			int64_t maxmp = pPlayer->GetAttr(C_MAX_MP);
			pPlayer->SetAttr(C_HP,maxhp,true);
			pPlayer->SetAttr(C_MP, maxmp, true);

			//竞技场重置所有技能CD
			SkillPart* pSkillPart = dynamic_cast<SkillPart*>(pPlayer->GetPart(PART_SKILL));
			if (nullptr != pSkillPart)
			{
				pSkillPart->RefreshAllSkillCDTime();
			}
		}
	}
	else if (CREATURE_REBOT == pCreature->CreatureKind())
	{
		CRebot *pRobot = dynamic_cast<CRebot*>(pCreature);
		if (nullptr != pRobot)
		{
			//机器人进入场景的时候，需要暂时停止其 AI，暂时没有这个接口，后面添加
			pRobot->SetPkMode(PK_MODE_KILLER);
			//设置满血满蓝
			pRobot->OnRevive(pRobot->GetCid());
			CreatureCommonAI *pAi = pRobot->GetAiData();
			if (nullptr != pAi)
			{
				pAi->StopAI();

			}
		}
	}
}

void ArenaDuplicate::CheckCountDown()
{
	if (!m_bStartCountDown)
	{
		return;
	}
	if (m_bStart)
	{
		return;
	}
	if ((int8_t)EDuplicateState::EDuplicateState_Begin == GetDuplicateState())
	{
		uint64_t curTime = g_GetGlobalServerTime()->UnixSec();
		if (curTime - m_nStartBrushTime > 60)
		{
			m_bEnd = true;
			m_nResult = RET_FAIL;
		}
	}
}

uint32_t ArenaDuplicate::GetAddArenaScore(int32_t result,uint32_t arenaStraight)
{
	if (RET_FAIL == result)
	{
		return 30;
	}

	if (arenaStraight <= 1)
	{
		return 60;
	}
	else if (arenaStraight == 2)
	{
		return 72;
	}
	else if (arenaStraight == 3)
	{
		return 84;
	}
	else if (arenaStraight == 4)
	{
		return 96;
	}

	return 108;
}

//开始挑战
int32_t ArenaDuplicate::StartChallenge(CharIDType charId)
{
	Player *pPlayer = GetPlayer(charId);
	if (nullptr == pPlayer)
	{
		return RET_FAIL;
	}
	//if (m_bStart)
	//{
	//	return RET_FAIL;
	//}
	if ((int8_t)EDuplicateState::EDuplicateState_Begin != GetDuplicateState())
	{
		return RET_FAIL;
	}
	m_bStart = true;
	m_nStartBrushTime = g_GetGlobalServerTime()->UnixSec();

	SET_UINT64::iterator  iterRebot = m_setRobot.begin();
	for (; iterRebot != m_setRobot.end(); ++iterRebot)
	{
		CRebot *pRebot = GetRobot((*iterRebot));
		if (nullptr != pRebot)
		{
			CreatureCommonAI *pAi = pRebot->GetAiData();
			if (nullptr != pAi)
			{
				pAi->SetAiEnable(true);
				//LogDebugFmtPrint("[logic] ArenaDuplicate::StartChallenge... SetAiEnable....");
			}
		}
	}

	return RET_SUCCESS;
}

//生物离开副本
void ArenaDuplicate::OnPlayerLeave(Player *pPlayer)
{
}

//是否能进入
bool ArenaDuplicate::OnCanEnter(Creature *pCreature)
{
	if (CREATURE_PLAYER ==  pCreature->CreatureKind() || CREATURE_REBOT == pCreature->CreatureKind())
	{
		return true;
	}

	return false;
}

//进入区域
bool ArenaDuplicate::OnEnterArea(uint32_t nAreaID)
{
	nAreaID = nAreaID;
	return true;
}
//复活
void ArenaDuplicate::OnRelive(Player *pPlayer, int8_t byType)
{
	pPlayer = pPlayer;
	byType = byType;
}

//下线
void ArenaDuplicate::PlayerLogoutGame(Player *pPlayer)
{
	if (nullptr == pPlayer)
	{
		return;
	}
	int8_t byState = GetDuplicateState();
	if (RET_SUCCESS != LeaveDuplicate(pPlayer))
	{
		LogErrFmtPrint("[logic] ArenaDuplicate::PlayerLogoutGame...LeaveDuplicate failed... state:%d , cid:%u ,duplicateid:%u, mapid:%u ", byState, pPlayer->GetCid(), m_nDuplicateID, m_nMapID);
	}

	LogDebugFmtPrint("[logic] ArenaDuplicate::PlayerLogoutGame.... state:%d , cid:%u ,duplicateid:%u, mapid:%u ", byState, pPlayer->GetCid(), m_nDuplicateID, m_nMapID);

}

//主动离开副本之前 的处理 (目前主要针对竞技场)
void ArenaDuplicate::OnActiveBeforeLeave(CharIDType cid)
{
	Player *pPlayer = GetPlayer(cid);
	if (nullptr != pPlayer)		//玩家离开，设置进入时的pk 模式
	{
		LogDebugFmtPrint("[logic] ArenaDuplicate::OnActiveBeforeLeave...sceneid:%u, dupid:%u ,cid:%lu, curhp:%lld, oldhp:%lld,  curmp:%lld, oldmp:%lld, pkmode:%d ", m_nSceneID, m_nDuplicateID, pPlayer->GetCid(), pPlayer->GetAttr(C_HP), m_oldhp, pPlayer->GetAttr(C_MP), m_oldmp, m_oldPkMode);
		if (m_oldPkMode != -1)
		{
			pPlayer->SetPkMode(m_oldPkMode);
		}

		if (m_oldhp != -1)
		{
			pPlayer->SetAttr(C_HP, m_oldhp, true);
		}
		if (m_oldmp != -1)
		{
			pPlayer->SetAttr(C_MP, m_oldmp, true);
		}
		
	}
	//离开竞技场，清除玩家身上的debuff
	if (nullptr != pPlayer)
	{
		BuffPart *pBuffPart = dynamic_cast<BuffPart*>(pPlayer->GetPart(PART_BUFF));
		if (nullptr != pBuffPart)
		{
			//
		}
	}

	Duplicate::OnActiveBeforeLeave(cid);


	//以下目前主要时针对竞技场，后续有需求再调整
	//因为跨逻辑节点切场景的时候会先保存数据，然后直接把玩家数据通过中心服带到目标逻辑节点了
	//所以需要在切场景之前 处理一次竞技场结果
	int32_t ret = CheckEnd();
	if (RET_SUCCESS == ret || RET_FAIL == ret)
	{
		if (!m_bNotifyArena)
		{
			NotifyCenterArenaResult(ret);
		}		
	}
}
//主动离开副本失败 处理 (目前主要针对竞技场)
void ArenaDuplicate::OnActiveLeaveFaild(CharIDType cid)
{
	//失败，在切回 杀戮模式
	Player *pPlayer = GetPlayer(cid);
	if (nullptr != pPlayer)
	{
	/*	pPlayer->SetPkMode(PK_MODE_KILLER);
		int32_t maxhp = pPlayer->GetAttr(C_MAX_HP);
		int32_t maxmp = pPlayer->GetAttr(C_MAX_MP);
		pPlayer->SetAttr(C_HP, maxhp, false);
		pPlayer->SetAttr(C_MP, maxmp, true);*/
	}	
}

//定时器更新
void ArenaDuplicate::OnTimerUpdate(uint32_t nTimerID)
{
	switch (nTimerID)
	{
	case ETimer_Update:
		{
			if (!m_bReadyTimeOut)//副本在准备状态下超时，说明玩家进入副本失败，或者玩家未进入副本
			{
				if (m_bEnd && !m_bNotifyArena)
				{
					//通知中心服结果
					NotifyCenterArenaResult(m_nResult);
				}
				//
				CheckCountDown();
			}
		}
		break;
	case ETimer_Clean:
		{
			OnCommon_CleanStateEnd();
		}
		break;
	case ETimer_Destory:
		{
			LogDebugFmtPrint("[logic] ArenaDuplicate destory .... duplicateid:%u , sceneid:%u, mapid:%u ", m_nDuplicateID, m_nSceneID, m_nMapID);
			//回收
			OnCommon_DestoryStateEnd();
		}
		break;
	default:
		break;
	}

}

void ArenaDuplicate::NotifyCenterArenaResult(int32_t result)
{

	LogInfoFmtPrint("[logic] ArenaDuplicate::OnTimerUpdate....dupid:%u, sceneid:%u, mapid:%u, result:%d, mirrorid:%lu,mirror_type:%d,result_dup:%d ", m_nDuplicateID, m_nSceneID, m_nMapID, result, m_paramEx.mirrorId, m_paramEx.mirrorType,m_nResult);

	if (ARENA_CHALLENGE_TYPE_CAMP_LEADER == m_paramEx.mirrorType) //挑战阵营镜像
	{

	}
	else
	{
		m_bNotifyArena = true;
		//挑战竞技场
		int32_t addScore = 0;
		//通知竞技场副本结果
		GWArenaChallResult arenaResult;
		arenaResult.set_srccharid(m_paramEx.keyValue);
		arenaResult.set_dstcharid(m_paramEx.mirrorId);
		arenaResult.set_type((ARENA_CHALLENGE_TYPE)m_paramEx.mirrorType);

		//Player *pPlayer = m_pScene->GetPlayer(m_paramEx.keyValue);
		//这里可能玩家离开场景了,update里面到下一帧的时候已经不再副本这个场景里面了，所以这里直接从生物管理器里面取
		Player *pPlayer = g_GetCreatureMgr()->GetPlayer(m_paramEx.keyValue);
		if (nullptr != pPlayer)
		{
			ArenaResultEvent resultEvent;
			if (RET_SUCCESS == result)
			{
				//增加连胜次数
				pPlayer->AddAttr(C_ARENA_STRAIGHT, 1, true);
				addScore = GetAddArenaScore(result,pPlayer->GetAttr(C_ARENA_STRAIGHT));
				arenaResult.set_ret(ACRE_WIN);
				arenaResult.set_srcscore(addScore);
				resultEvent.isWin = true;
			}
			else
			{
				//失败重置连胜
				pPlayer->SetAttr(C_ARENA_STRAIGHT, 0, true);
				addScore = GetAddArenaScore(result,pPlayer->GetAttr(C_ARENA_STRAIGHT));
				arenaResult.set_ret(ACRE_LOSE);
				arenaResult.set_srcscore(addScore);
				resultEvent.isWin = false;
			}

			//pPlayer->AddAttr(C_ARENA_SCORE, addScore, true);
			pPlayer->AddSourceAttr(C_ARENA_SCORE, addScore, true, S_ARENA);

			//积分改变事件
			ArenaScoreEvent scoreEvent;
			scoreEvent.score = addScore;
			g_GetEvent()->FireExecute(EVENT_ARENA_SCORE_CHANGE, pPlayer->GetCid(), pPlayer->CreatureKind(), (ArenaScoreEvent*)&scoreEvent, sizeof(scoreEvent));

			//触发事件
			g_GetEvent()->FireExecute(EVENT_ARENA_RESULT, pPlayer->GetCid(), pPlayer->CreatureKind(), (ArenaResultEvent*)&resultEvent, sizeof(resultEvent));
		}
		//如果找不到玩家（正常情况下不可能取不到 取不到的话默认当成失败处理）
		else
		{
			arenaResult.set_ret(ACRE_LOSE);
			arenaResult.set_srcscore(0);
		}

		//发送到中心服
		if (!g_GetLogicService()->SendDataToCenter(EMODULE_ID_ARENA, LOGIC_TO_CENTER_ARENA_CHALL_RESULT, &arenaResult))
		{
			LogErrFmtPrint("[logic] ArenaDuplicate::OnTimerUpdate....SendDataToCenter failed....dupid:%u, sceneid:%u, keyvalue:%u, mirrorid:%u, mirrortype:%d ", m_nDuplicateID, m_nSceneID, (uint32_t)m_paramEx.keyValue, m_paramEx.mirrorId, m_paramEx.mirrorType);
		}
	}
}

//执行事件
void ArenaDuplicate::OnExecuteEvent(uint16_t nEventID, uint32_t nSrcID, uint8_t bySrcType, void *pContext, int32_t nLen)
{
	switch (nEventID)
	{
	case EVENT_CREATURE_DEAD:
	{
	}
	break;
	case EVENT_ENTER_SCENE:
	{
	}
	break;
	case EVENT_DISCONNECT:
	{
	}
	break;
	}
}

void ArenaDuplicate::OnReady_State()
{

}

void ArenaDuplicate::OnBegin_State()
{	
	m_bStartCountDown = true;
}

void ArenaDuplicate::OnFinish_State()
{
	//完成之后，停止机器人AI
	SET_UINT64 setRobot = m_setRobot;
	SET_UINT64::iterator iter = setRobot.begin();
	for (; iter != setRobot.end(); ++iter)
	{
		CRebot *pRobot = GetRobot((*iter));
		if (nullptr != pRobot)
		{
			CreatureCommonAI *pAi = pRobot->GetAiData();
			if (nullptr != pAi)
			{
				pAi->StopAI();

			}
		}
	}

	LogDebugFmtPrint("[logic] ArenaDuplicate::OnFinish_State....dupid:%u, sceneid:%u, mapid:%u, result:%d ", m_nDuplicateID, m_nSceneID, m_nMapID, m_nResult);


	//竞技场副本完成之后直接切换到清理状态
	SetDuplicateState((int8_t)EDuplicateState::EDuplicateState_Clean);
}

void ArenaDuplicate::OnFlop_State()
{
	//设置抽奖时间 15s
	LogDebugFmtPrint("[logic] ArenaDuplicate::OnDuplicateState_Flop....duplicateid:%u , sceneid:%u ", m_nDuplicateID, m_nSceneID);
	OnCommon_DupFlopState();
}

void ArenaDuplicate::OnClean_State()
{
	OnCommon_DupCleanState();
}

void ArenaDuplicate::OnDestory_State()
{
	//fix by lian 这里要先通知中心服竞技场结束了  
	//如果有玩家下线了 然后重新上线 这时候会触发玩家离开游戏事件 然后程序会走到OnDestory_State函数
	//NotifyCenterArenaResult接口中需要取玩家指针 如果这里不先调用NotifyCenterArenaResult接口 会导致副本update定时器到了之后就取不到角色指针了 因为角色指针在OnDestory_State执行完就会被回收到了
	//NotifyCenterArenaResult();
	OnCommon_DupDestoryState();
}